﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Farigola.Engine.Factories;
using Farigola.Engine.SystemData;
using Farigola.Engine.SystemData.Entity;
using Farigola.Engine.SystemData.Entity.inst;
using Farigola.Engine.SystemData.Entity.Type;
using Farigola.Engine.SystemData.DataValue;

namespace Farigola.Engine
{
    /// <summary>
    /// The structure of a project, inner objet of a project.
    /// low-level/technical methods on the project.
    /// 
    /// </summary>
    public class ProjectStruct
    {
        /// <summary>
        /// The factory to build all object: workspace, project, and all
        /// domain objects of the application.
        /// </summary>
        private Factory _factory;

        /// <summary>
        /// The unique errors manager of the engine application.
        /// Provided to main object in the engine (workspace, project,...).
        /// </summary>
        //private ErrorMgr _errorMgr;

        /// <summary>
        /// Manager of tasks activity in the application (trace)
        /// Manage alos errors occurs in the engine.
        /// </summary>
        private AppActivityMgr _appActivityMgr;

        /// <summary>
        /// For (only) builtin types and data.
        /// provided by the workspace.
        /// </summary>
        private SystemDataMgr _systemDataMgr;

        /// <summary>
        /// typeMgr for types created in the project
        /// (!) types and data are placed in the datatree under the root folder.
        /// the type mgr is only to accelerate accessing types.
        /// </summary>
        private TypeMgr _typeMgr;

        /// <summary>
        /// The object to find instances in the entities of the project.
        /// scan entities from the root folder.
        /// The finder will be active after root folders will be created.
        /// </summary>
        private EntityFinder _entityFinder;

        /// <summary>
        /// The date time of the creation of the project.
        /// </summary>
        private DateTime _dateCreation;

        /// <summary>
        /// the id of the project, to differentiate projects.
        /// </summary>
        private EntityId _id;

        /// <summary>
        /// The name of the project.
        /// Can not be null or empty.
        /// </summary>
        private String _name;

        /**
         * The root folder of data contained in the project.
         * has no parent (= null).
         * name is:  $$$prj_root 
         * 
         * has only 2 childs: 
         *   $$$prj_root_system    system/internal data of the project
         *   $$$prj_root_user        user data, types and entities
         */
        private EntInstFolder _rootFolder;

        /**
         * The root folder for data system.
         * child of the root folder of the project.
         * name is: $$$prj_root_system    system/internal data of the project
         * 
         */
        private EntInstFolder _rootSystemFolder;

        /**
         * The root folder of user data.
         * child of the root folder of the project.
         * 
         * name is: $$$prj_root_user        user data, types and entities
         */
        private EntInstFolder _rootUserFolder;


        //---------------------------------------------------------------------
        /// <summary>
        /// Constructor.
        /// </summary>
        public ProjectStruct(Factory factory, AppActivityMgr appActivityMgr)
        {
            _dateCreation = DateTime.Now;

            _factory = factory;

            _appActivityMgr = appActivityMgr;

            // get the existing mgr, createed by the workspace 
            _systemDataMgr = _factory.GetSystemDataMgr();

            // create a specific mgr
            _typeMgr = _factory.CreateTypeMgr();

            // create the entity finder
            _entityFinder = _factory.CreateEntityFinder(_systemDataMgr, _typeMgr); 

        }

        //=====================================================================
        #region Checks methods.

        //---------------------------------------------------------------------
        /// <summary>
        /// Check the 3 root folders.
        /// do a basic test.
        /// </summary>
        /// <returns></returns>
        public bool CheckInternalAllRootFolder()
        {
            if (_rootFolder == null)
                return false;

            if (_rootSystemFolder == null)
                return false;
            if (_rootUserFolder == null)
                return false;
            return true;
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Check the workspace internal content, after init.
        /// a basic check, if an error occurs, return false.
        /// 
        /// TODO: add parameter errListCode
        /// </summary>
        /// <returns></returns>
        public bool CheckInternal(out string errListCode)
        {
            errListCode = "";

            if (_factory == null)
            {
                errListCode = EngineDef.ErrorCode.ProjectStructFactoryIsNull.ToString();
                //return false;
            }

            if (_systemDataMgr == null)
            {
                errListCode += ";"+ EngineDef.ErrorCode.ProjectStructSystemDataMgrIsNull.ToString();
                //return false;
            }

            if (_typeMgr == null)
            {
                errListCode = ";" + EngineDef.ErrorCode.ProjectStructTypeMgrMgrIsNull.ToString();
                //return false;
            }

            if (errListCode.Length > 0)
                return false;

            if (_id == null)
                // todo: add error
                return false;

            if (_name == null)
                // todo: add error
                return false;

            if (!_systemDataMgr.CheckInternal())
                // todo: add error
                return false;

            // check the 3 root folders
            if (!CheckInternalAllRootFolder())
                // todo: add error
                return false;

            if (!_entityFinder.CheckInternal())
                // todo: add error
                return false;

            // ok, no error
            return true;
        }

        #endregion

        //=====================================================================
        #region Get/Set methods.

        //---------------------------------------------------------------------
        public Factory GetFactory()
        {
            return _factory;
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// return the tool to find entities in the project.
        /// </summary>
        /// <returns></returns>	
        public EntityFinder GetEntityFinder()
        {
            return _entityFinder;
        }

        //---------------------------------------------------------------------
        public SystemDataMgr GetSystemDataMgr()
        {
            return _systemDataMgr;
        }

        //---------------------------------------------------------------------
        public AppActivityMgr GetAppActivityMgr()
        {
            return _appActivityMgr;
        }

        //---------------------------------------------------------------------
        public bool SetId(EntityId id)
        {
            _id = id;
            return true;
        }

        //---------------------------------------------------------------------
        public EntityId GetId()
        {
            return _id;
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Set a date of creation of the project, used when project are load.
        /// </summary>
        /// <param name="dateCre"></param>
        public void SetDateCreation(DateTime dateCre)
        {
            _dateCreation = dateCre;
        }

        //---------------------------------------------------------------------
        public bool SetName(string name)
        {
            // check the name
            // todo:

            _name = name;
            return true;
        }

        //---------------------------------------------------------------------
        public string GetName()
        {
            return _name;
        }

        //---------------------------------------------------------------------
        public DateTime GetDateCreation()
        {
            return _dateCreation;
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// exp:
        /// "dd/MM/yyyy HH:mm:ss"
        /// </summary>
        /// <param name="format"></param>
        /// <returns></returns>
        public string GetDateCreationStr(string format)
        {
            try
            {
                return _dateCreation.ToString(format);
            }
            catch
            {
                return "";
            }
        }

        #endregion

        //---------------------------------------------------------------------
        /// <summary>
        /// Return the main root folder of the project,*has no parent (=null). 
        /// </summary>
        /// <returns></returns>
        public EntInstFolder GetRootFolder()
        {
            return _rootFolder;
        }

        //---------------------------------------------------------------------
        public EntInstFolder GetRootUserFolder()
        {
            return _rootUserFolder;
        }

        //---------------------------------------------------------------------
        public EntInstFolder GetRootSystemFolder()
        {
            return _rootSystemFolder;
        }

        //---------------------------------------------------------------------
        public bool SetRootFolder(EntInstFolder rootFolder)
        {
            // check the root folders
            if (rootFolder == null)
                return false;

            // is already set, error
            if (_rootFolder != null)
                return false;

            // set the root folder
            _rootFolder = rootFolder;
            return true;
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Set all root folders, a root and 2 root childs.
        /// Need all to make special link to each root. 
        ///  
        /// $$$prj_root, 
        ///  		$$$prj_root_system, 
        /// 		$$$prj_root_user		all user entities comes here.
        ///
        /// </summary>
        /// <param name="rootFolder"></param>
        /// <returns></returns>
        public bool SetAllRootFolder(EntInstFolder rootFolder)
        {
            // check the root folders
            if (rootFolder == null)
                return false;

            // is already set, error
            if (_rootFolder != null)
                return false;

            // set the root folder
            _rootFolder = rootFolder;

            // set 2 others root folder, user and system
            _rootSystemFolder = (EntInstFolder)_rootFolder.FindChildByName(EntityDef.prjRootSystemFolderName);
            _rootUserFolder = (EntInstFolder)_rootFolder.FindChildByName(EntityDef.prjRootUserFolderName);

            // provide the root folder to the entity finder of the project
            _entityFinder.SetProjectRootFolder(_rootFolder);

            return true;
        }

        //=====================================================================
        #region Attach/detach entity instances/type class methods.

        //---------------------------------------------------------------------
        /// <summary>
        /// Attach the entity (instance or type) to its folder parent.
        /// and for folder, set the parent.
        /// </summary>
        /// <param name="parentFolder"></param>
        /// <param name="ent"></param>
        /// <returns></returns>
        public bool AttachEntityToParentFolder(EntInstFolder parentFolder, EntityBase ent)
        {
            bool res;

            // do basic checks
            if (parentFolder == null)
                return false;

            if (ent == null)
                return false;

            // todo: do it better! manage the return...
            res = parentFolder.AddChild(ent);

            // if the ent child is an ent inst folder, set the parent
            if (ent is EntInstFolder)
                (ent as EntInstFolder).SetParentFolder(parentFolder);

            return res;
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Attach the entity instance to its folder parent.
        /// </summary>
        /// <param name="parentFolder"></param>
        /// <param name="entInst"></param>
        /// <returns></returns>
        public bool AttachEntInstToParentFolder(EntInstFolder parentFolder, EntInstBase entInst)
        {
            return AttachEntityToParentFolder(parentFolder, entInst);
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Attach the entity type class to its folder parent.
        /// </summary>
        /// <param name="parentFolder"></param>
        /// <param name="ent"></param>
        /// <returns></returns>
        public bool AttachEntTypeClassToParentFolder(EntInstFolder parentFolder, EntTypeClassBase ent)
        {
            return AttachEntityToParentFolder(parentFolder, ent);
        }

        #endregion

        //=====================================================================
        #region Create entity instances basic type methods.

        //---------------------------------------------------------------------
        /// <summary>
        /// Create an entity instance.
        /// Do some checks before create.
        /// If the folderParent is null, attach the inst under the root folder.
        /// Only for basic type: string, int,...
        ///  
        /// its a low-level method.
        /// </summary>
        /// <param name="parentFolder"></param>
        /// <param name="entType"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public EntInstBasicBase createEntInstBasicBase(EntInstFolder parentFolder, EntTypeBase entType, String name)
        {
            bool res;

            // if the parent folder is null, set the root folder user
            EntInstFolder fold;
            if (parentFolder == null)
                fold = _rootFolder;
            else
                fold = parentFolder;

            // the parent folder must be present in the project
            // todo: utiliser l'EntityFinder

            // check the type, must be a type basic (the method parameter must be generic)
            if (!(entType is EntTypeBasicBase))
                return null;

            // check if the name is right
            if (!_factory.GetFactoryCommon().checkSyntaxName(name))
                return null;

            // check that the name is not used by a "brother" entity, under the parent folder 
            if (_entityFinder.FindEntityByName(EntityFinder.FindSystemUserType.All, parentFolder, name, false) != null)
                return null;

            // now create the entity instance, depending on type
            EntInstBasicBase inst = _factory.GetFactoryEntity().CreateEntInstBasicBase(entType, name);

            // error?
            if (inst == null)
                return null;

            // attach the entity to its folder parent
            res = AttachEntInstToParentFolder(fold, inst);
            if (!res)
                return null;

            // ok the entity instance was created and attach to its parent
            return inst;
        }

        //---------------------------------------------------------------------
        /**
         * create a folder under a parent folder.
         * 
         * if the parent folder is null, its the root folder user.
         *  
         * @param parentFolder
         * @param name
         * @return
         */
        public EntInstFolder createEntInstFolder(EntInstFolder parentFolder, String name)
        {
            bool res;

            // if the parent folder is null, set the root folder user
            EntInstFolder fold;
            if (parentFolder == null)
                fold = _rootFolder;
            else
                fold = parentFolder;

            // the parent folder must be present in the project
            // todo: utiliser l'EntityFinder


            // check if the name is right
            if (!_factory.GetFactoryCommon().checkSyntaxName(name))
                return null;

            // check that the name is not used by a "brother" entity, under the parent folder 
            if (_entityFinder.FindEntityByName(EntityFinder.FindSystemUserType.All, parentFolder, name, false) != null)
                return null;

            // now create the entity instance, depending on type
            EntInstFolder inst = _factory.GetFactoryEntity().CreateEntInstFolder(name);

            // error?
            if (inst == null)
                return null;

            // attach the entity to its folder parent
            res = AttachEntInstToParentFolder(fold, inst);
            if (!res)
                return null;

            // ok the entity instance was created and attach to its parent
            return inst;
        }

        #endregion

        //=====================================================================
        #region Create entity type class methods.


        //---------------------------------------------------------------------
        /**
         * Create an entity type class (type class or type class anonym).
         * Do some checks before create.
         * 
         * low-level
         * @param parentFolder
         * @param entType
         * @param name
         * @return
         */
        public EntTypeClassBase createEntTypeClassBase(EntInstFolder parentFolder, String typeClassBaseName, String name)
        {
            bool res;

            // if the parent folder is null, set the root folder user
            EntInstFolder fold;
            if (parentFolder == null)
                fold = _rootFolder;
            else
                fold = parentFolder;

            // the parent folder must be present in the project
            // todo: utiliser l'EntityFinder

            // check if the name is right
            if (name == null)
                return null;
            name = name.Trim();
            if (name.Length == 0)
                return null;

            // check if the name is not used by another type class entity, in all the project, from the root folder
            EntTypeClassBase typeClass = _entityFinder.FindEntTypeClassByName(EntityFinder.FindSystemUserType.All, GetRootFolder(), name, true);
            if (typeClass != null)
                return null;

            // now create the entity type class (stad or anonym)
            typeClass = _factory.GetFactoryEntity().CreateEntTypeClassBase(typeClassBaseName, name);

            // error?
            if (typeClass == null)
                return null;

            // attach the entity to its folder parent
            res = AttachEntTypeClassToParentFolder(fold, typeClass);
            if (!res)
                return null;

            // ok the entity type class was created and attach to its parent
            return typeClass;
        }

        #endregion

        //=====================================================================
        #region Create entity instances class methods.

        //---------------------------------------------------------------------
        /// <summary>
        /// Create the instance class empty (with no inst DM).
        /// create instclass std or anonym.
        ///
        /// </summary>
        /// <param name="parentFolder"></param>
        /// <param name="systOrUser"></param>
        /// <param name="entType"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public EntInstClass createEntInstClassEmpty(EntInstFolder parentFolder, EntityDef.TypeSystOrUser systOrUser, EntTypeBase entType, String name)
        {
            bool res;

            // if the parent folder is null, set the root folder user
            EntInstFolder fold;
            if (parentFolder == null)
                fold = _rootFolder;
            else
                fold = parentFolder;

            // the parent folder must be present in the project
            // todo: utiliser l'EntityFinder

            // check the type, must be a type basic (the method parameter must be generic)
            if (!(entType is EntTypeClassBase))
                return null;

            // check if the name is right
            if (!_factory.GetFactoryCommon().checkSyntaxName(name))
                return null;

            // check that the name is not used by a "brother" entity, under the parent folder 
            if (_entityFinder.FindEntityByName(EntityFinder.FindSystemUserType.All, parentFolder, name, false) != null)
                return null;

            // now create the entity instance, depending on type
            EntInstClass inst = _factory.GetFactoryEntity().CreateEntInstClassEmpty(systOrUser, entType, name);

            // error?
            if (inst == null)
                return null;

            // attach the entity to its folder parent
            res = AttachEntInstToParentFolder(fold, inst);
            if (!res)
                return null;

            // ok the entity instance was created and attach to its parent
            return inst;
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Add a data member to a type class.
        /// </summary>
        /// <param name="typeClass"></param>
        /// <param name="nameDM"></param>
        /// <param name="typeDM"></param>
        /// <returns></returns>
        public EntTypeClassDataMember AddTypeClassDataMember(EntTypeClassBase typeClass, String nameDM, EntTypeBase typeDM)
        {
            // check the typeClass, must be not null 
            if (typeClass == null)
                return null;
            // check the typeClass, must be present in the project
            // todo:

            // check the name of the DM
            if (!_factory.GetFactoryCommon().checkSyntaxNameTypeClassDataMember(nameDM))
                return null;

            // check that a DM with the same name doesn't exists
            if (_entityFinder.FindTypeClassDataMemberByName(typeClass, nameDM) != null)
                return null;

            // create the data member of the type class, set the name and the type
            EntTypeClassDataMember typeClassDM = _factory.GetFactoryEntity().CreateEntTypeClassDataMember(typeDM, nameDM);
            if (typeClassDM == null)
                return null;

            // add the created DM to the typeClass
            if (!typeClass.addDataMember(typeClassDM))
                return null;

            // return the created typeClass data member
            return typeClassDM;
        }


        //---------------------------------------------------------------------
        /**
         * Create one data member instance of the inst class.
         * 
         * @param instClass
         * @param typeClassDM
         * @return
         */
        public bool createInstClassDataMember(EntInstClass instClass, EntTypeClassDataMember typeClassDM)
        {
            if (instClass == null)
                return false;

            if (typeClassDM == null)
                return false;

            // create the DM inst of the inst class (not attach the DM to the inst class)
            EntInstBase instDM = _factory.GetFactoryEntity().CreateInstClassDataMember(instClass, typeClassDM);
            if (instDM == null)
                return false;

            // attach it to the ent class
            return _factory.GetFactoryEntity().AttachEntInstDataMemberToInstClass(instClass, typeClassDM, instDM);
        }

        //---------------------------------------------------------------------
        /**
         * create all instances data member of the instance class.
         * 
         * @param instClass
         * @return
         */
        public bool createInstClassAllDataMember(EntInstClass instClass)
        {
            bool res;

            if (instClass == null)
                return false;

            // scan all typeDM
            EntTypeClass typeClass = instClass.getEntTypeClass();
            foreach (EntTypeClassDataMember typeClassDM in typeClass.listDataMember())
            {
                // create the ent inst class DM and attach it
                res = createInstClassDataMember(instClass, typeClassDM);
                // stop on the first error found
                if (!res)
                    return false;
            }
            // ok DM inst of the inst class are created
            return true;
        }


        #endregion

        //=====================================================================
        #region Create entity instances class anonym methods.

        //---------------------------------------------------------------------
        /// <summary>
        /// Add a DM inst to a entity instance class anonym.
        /// </summary>
        /// <param name="instClassAnonym"></param>
        /// <param name="typeDM"></param>
        /// <param name="nameDM"></param>
        /// <returns></returns>
        public EntInstBase AddInstClassAnonymDataMember(EntInstClassAnonym instClassAnonym, EntTypeBase typeDM, String nameDM)
        {
            if (instClassAnonym == null)
                return null;

            // check that the inst class is present in the project, search from the root folder
            // todo:

            // check the syntax name of the inst DM 
            if (!_factory.GetFactoryCommon().checkSyntaxName(nameDM))
                return null;

            // check that the name is not used by another inst DM of the inst
            if (instClassAnonym.FindEntInstDataMemberByName(nameDM) != null)
                // sorry, an instDM with this name already exists
                return null;

            // check that is possible to create an instDM with this type
            // todo:  limitation, only type basic (string,...) is possible today
            // todo: ask to factoryEntity

            EntInstBase entInstDM = null;

            // is the type is type basic?
            if (_factory.GetFactoryCommon().IsEntTypeBasic(typeDM))
                entInstDM = _factory.GetFactoryEntity().CreateEntInstBasicBase(typeDM, EntityDef.TypeSystOrUser.User, _factory.GetFactoryCommon().CreateEntityId(), nameDM);

            // other type?
            // todo:

            // -> so create inst DM basic type
            // ici dans une methode de la factory???

            if (entInstDM == null)
                return null;

            // attach the instDM to the inst class anonym
            bool res = instClassAnonym.addEntInstDataMember(entInstDM);
            if (!res)
                return null;

            // ok, return the new inst DM
            return entInstDM;
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// Add a DM inst to a entity instance class anonym.
        /// </summary>
        /// <param name="instClassAnonym"></param>
        /// <param name="typeNameDM"></param>
        /// <param name="nameDM"></param>
        /// <returns></returns>
        public EntInstBase AddInstClassAnonymDataMember(EntInstClassAnonym instClassAnonym, String typeNameDM, String nameDM)
        {
            // get the type, by the name (all to find builtin type)
            EntTypeBase typeBase = _entityFinder.FindEntTypeBaseByName(typeNameDM);
            if (typeBase == null)
                return null;

            // create the inst DM
            return AddInstClassAnonymDataMember(instClassAnonym, typeBase, nameDM);
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// create an instance class anonym, under the root parent.
        /// If the folderParent is null, attach the inst under the root folder.
        /// </summary>
        /// <param name="parentFolder"></param>
        /// <param name="systOrUser"></param>
        /// <param name="name"></param>
        /// <returns></returns>
        public EntInstClassAnonym CreateEntInstClassAnonym(EntInstFolder parentFolder, EntityDef.TypeSystOrUser systOrUser, String name)
        {
            bool res;

            // if the parent folder is null, set the root folder user
            EntInstFolder fold;
            if (parentFolder == null)
                fold = _rootFolder;
            else
                fold = parentFolder;

            // the parent folder must be present in the project
            // todo: utiliser l'EntityFinder

            // check if the name is right
            if (!_factory.GetFactoryCommon().checkSyntaxName(name))
                return null;

            // check that the name is not used by a "brother" entity, under the parent folder 
            if (_entityFinder.FindEntityByName(EntityFinder.FindSystemUserType.All, parentFolder, name, false) != null)
                return null;

            // now create the entity instance class anonym
            EntInstClassAnonym inst = _factory.GetFactoryEntity().CreateEntInstClassAnonymEmpty(systOrUser, name);

            // error?
            if (inst == null)
                return null;

            // attach the entity to its folder parent
            res = AttachEntInstToParentFolder(fold, inst);
            if (!res)
                return null;

            // ok the entity instance was created and attach to its parent
            return inst;
        }

        #endregion

        //=====================================================================
        #region Create entity instances structure (list,...).

        //---------------------------------------------------------------------
        /// <summary>
        /// create an inst list of items, under the provided root folder.
        /// Here items are Entities instances, (not DataValue).
        /// </summary>
        /// <param name="parentFolder"></param>
        /// <param name="systOrUser"></param>
        /// <param name="entTypeItem"></param>
        /// <param name="listName"></param>
        /// <returns></returns>
        public EntInstStructList CreateEntInstStructListEnt(EntInstFolder parentFolder, EntityDef.TypeSystOrUser systOrUser, EntTypeBase entTypeItem, string listName)
        {
            if (parentFolder == null)
                parentFolder = GetRootSystemFolder();

            // the parent folder must be present in the project
            // todo: utiliser l'EntityFinder

            // check the type of items
            if (entTypeItem == null)
                return null;

            // only type basic are possible today, no class, (and of course no folder!)
            if (!_factory.GetFactoryCommon().IsEntTypeBasic(entTypeItem))
                return null;


            // check if the name is right
            if (!_factory.GetFactoryCommon().checkSyntaxName(listName))
                return null;

            // check that the name is not used by a "brother" entity, under the parent folder 
            if (_entityFinder.FindEntityByName(EntityFinder.FindSystemUserType.All, parentFolder, listName, false) != null)
                return null;

            // now create the entity instance list
            EntInstStructList instList = _factory.GetFactoryEntity().CreateEntInstStructList(systOrUser, entTypeItem, listName);

            // error?
            if (instList == null)
                return null;

            // attach the entity to its folder parent
            bool res = AttachEntInstToParentFolder(parentFolder, instList);
            if (!res)
                return null;

            // ok the entity instance was created and attached to its parent
            return instList;
        }

        //---------------------------------------------------------------------
        /// <summary>
        /// create an inst list of items, under the provided root folder.
        /// Here items are data value, (not Entities instances).
        /// </summary>
        /// <param name="parentFolder"></param>
        /// <param name="systOrUser"></param>
        /// <param name="entTypeItem"></param>
        /// <param name="listName"></param>
        /// <returns></returns>
        public EntInstStructList CreateEntInstStructList(EntInstFolder parentFolder, EntityDef.TypeSystOrUser systOrUser, DataValueType dataValueType, string listName)
        {
            if (parentFolder == null)
                parentFolder = GetRootSystemFolder();

            // the parent folder must be present in the project
            // todo: utiliser l'EntityFinder

            // check the type of items
            if (dataValueType == DataValueType.Undefined)
                return null;

            // check if the name is right
            if (!_factory.GetFactoryCommon().checkSyntaxName(listName))
                return null;

            // check that the name is not used by a "brother" entity, under the parent folder 
            if (_entityFinder.FindEntityByName(EntityFinder.FindSystemUserType.All, parentFolder, listName, false) != null)
                return null;

            // now create the entity instance list
            EntInstStructList instList = _factory.GetFactoryEntity().CreateEntInstStructList(systOrUser, dataValueType, listName);

            // error?
            if (instList == null)
                return null;

            // attach the entity to its folder parent
            bool res = AttachEntInstToParentFolder(parentFolder, instList);
            if (!res)
                return null;

            // ok the entity instance was created and attached to its parent
            return instList;
        }


        #endregion
    }
}
